Passed
Pull Request — master (#1)
by Muhammad Dyas
01:35
created

vote.ts ➔ choice   A

Complexity

Conditions 1

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 33
rs 9.4
c 0
b 0
f 0
cc 1
1
import {chat_v1 as chatV1} from 'googleapis/build/src/apis/chat/v1';
2
import {PollState, Voter, Votes} from './interfaces';
3
4
/**
5
 * Creates a small progress bar to show percent of votes for an option. Since
6
 * width is limited, the percentage is scaled to 20 steps (5% increments).
7
 *
8
 * @param {number} choice - The choice index
9
 * @param {object} voter - The voter
10
 * @param {object} votes - Total votes cast in the poll
11
 * @param {boolean} isAnonymous - save name or not
12
 * @returns {Votes} Map of cast votes keyed by choice index
13
 */
14
export function saveVotes(choice: number, voter: Voter, votes: Votes, isAnonymous = false) {
15
  Object.keys(votes).forEach(function(choiceIndex) {
16
    if (votes[choiceIndex]) {
17
      const existed = votes[choiceIndex].findIndex((x) => x.uid === voter.uid);
18
      if (existed > -1) {
19
        votes[choiceIndex].splice(existed, 1);
20
      }
21
    }
22
  });
23
  if (isAnonymous) {
24
    delete voter.name;
25
  }
26
  if (votes[choice]) {
27
    votes[choice].push(voter);
28
  } else {
29
    votes[choice] = [voter];
30
  }
31
32
  return votes;
33
}
34
35
/**
36
 * Creates a small progress bar to show percent of votes for an option. Since
37
 * width is limited, the percentage is scaled to 20 steps (5% increments).
38
 *
39
 * @param {number} voteCount - Number of votes for this option
40
 * @param {number} totalVotes - Total votes cast in the poll
41
 * @returns {string} Text snippet with bar and vote totals
42
 */
43
export function progressBarText(voteCount: number, totalVotes: number) {
44
  if (voteCount === 0 || totalVotes === 0) {
45
    return '';
46
  }
47
48
  // For progress bar, calculate share of votes and scale it
49
  const percentage = (voteCount * 100) / totalVotes;
50
  const progress = Math.round((percentage / 100) * 35);
51
  return '█'.repeat(progress);
52
}
53
54
/**
55
 * Builds a line in the card for a single choice, including
56
 * the current totals and voting action.
57
 *
58
 * @param {number} i - Index to identify the choice
59
 * @param {object} state - Text of the choice
60
 * @param {number} totalVotes - Total votes cast in poll state
61
 * @param {string} serializedState - Serialized poll state to send in events
62
 * @param {string} creator - creator of the option
63
 * @returns {chatV1.Schema$GoogleAppsCardV1Section} card section
64
 */
65
export function choiceSection(i: number, state: PollState, totalVotes: number, serializedState: string, creator = '') {
66
  if (state.votes[i] === undefined) {
67
    state.votes[i] = [];
68
  }
69
  const voteCount = state.votes[i].length;
70
  const choiceTag = choice(i, state.choices[i], voteCount, totalVotes, serializedState);
71
  if (creator) {
72
    choiceTag.decoratedText.topLabel = 'Added by ' + creator;
73
  }
74
  const section: chatV1.Schema$GoogleAppsCardV1Section = {
75
    'widgets': [choiceTag],
76
  };
77
  if (state.votes[i].length > 0 && !state.anon) {
78
    section.collapsible = true;
79
    section.uncollapsibleWidgetsCount = 1;
80
    section.widgets.push({
81
      'textParagraph': {
82
        'text': state.votes[i].map((u) => u.name).join(', '),
83
      },
84
    });
85
  }
86
  return section;
87
}
88
89
/**
90
 * Builds a line in the card for a single choice, including
91
 * the current totals and voting action.
92
 *
93
 * @param {number} index - Index to identify the choice
94
 * @param {string|undefined} text - Text of the choice
95
 * @param {number} voteCount - Current number of votes cast for this item
96
 * @param {number} totalVotes - Total votes cast in poll
97
 * @param {string} state - Serialized state to send in events
98
 * @returns {chatV1.Schema$GoogleAppsCardV1Widget} card widget
99
 */
100
function choice(
101
    index: number, text: string, voteCount: number, totalVotes: number,
102
    state: string): chatV1.Schema$GoogleAppsCardV1Widget {
103
  const progressBar = progressBarText(voteCount, totalVotes);
104
  return {
105
    decoratedText: {
106
      bottomLabel: `${progressBar} ${voteCount}`,
107
      text: text,
108
      button: {
109
        text: 'vote',
110
        onClick: {
111
          action: {
112
            function: 'vote',
113
            parameters: [
114
              {
115
                key: 'state',
116
                value: state,
117
              },
118
              {
119
                key: 'index',
120
                value: index.toString(10),
121
              },
122
            ],
123
          },
124
        },
125
      },
126
    },
127
  };
128
}
129